﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace AuxEnvironment
{
    public enum TextSticking { TS_CENTER, TS_TOP, TS_BOTTOM, TS_LEFT, TS_RIGHT };

    public class TextRenderer
    {
        private Font FontValue;
        private string LabelValue;
        private bool NeedToCalculateSize, NeedToRenderTexture;
        private Texture Tex;
        private int CalculatedWidth, CalculatedHeight;
        private TextSticking TS = TextSticking.TS_CENTER;

        public Font Font
        {
            get
            {
                return FontValue;
            }

            set
            {
                FontValue = value;
                NeedToCalculateSize = true;
                NeedToRenderTexture = true;
            }
        }
        public string Label
        {
            get
            {
                return LabelValue;
            }

            set
            {
                if (value != LabelValue)
                {
                    LabelValue = value;
                    NeedToCalculateSize = true;
                    NeedToRenderTexture = true;
                }
            }
        }
        public int Width
        {
            get
            {
                if (NeedToCalculateSize)
                {
                    CalculateSize();
                }
                return CalculatedWidth;
            }
        }
        public int Height
        {
            get
            {
                if (NeedToCalculateSize)
                {
                    CalculateSize();
                }
                return CalculatedHeight;
            }
        }
        public Color4 Color = Color4.Black;

        public TextRenderer()
        {
        }

        public TextRenderer(Font Font)
        {
            this.Font = Font;
        }
        
        public TextRenderer(Font Font, TextSticking TS)
        {
            this.Font = Font;
            this.TS = TS;
        }

        public TextRenderer(Font Font, Color4 Color)
        {
            this.Font = Font;
            this.Color = Color;
        }

        public TextRenderer(Font Font, Color4 Color, TextSticking TS)
        {
            this.Font = Font;
            this.Color = Color;
            this.TS = TS;
        }

        public TextRenderer(Font Font, string Label)
        {
            this.Font = Font;
            this.Label = Label;
        }

        public TextRenderer(Font Font, string Label, TextSticking TS)
        {
            this.Font = Font;
            this.Label = Label;
            this.TS = TS;
        }

        public TextRenderer(Font Font, Color4 Color, string Label)
        {
            this.Font = Font;
            this.Color = Color;
            this.Label = Label;
        }

        public TextRenderer(Font Font, Color4 Color, string Label, TextSticking TS)
        {
            this.Font = Font;
            this.Color = Color;
            this.Label = Label;
            this.TS = TS;
        }
        
        private void CalculateSize()
        {
            using (var Bitmap = new Bitmap(1, 1))
            {
                using (Graphics Graphics = Graphics.FromImage(Bitmap))
                {
                    var Measures = Graphics.MeasureString(Label, Font);
                    CalculatedWidth = (int)Math.Ceiling(Measures.Width);
                    CalculatedHeight = (int)Math.Ceiling(Measures.Height);
                }
            }
            NeedToCalculateSize = false;
        }

        public void Render(float X, float Y)
        {
            if ((null == Label) || ("" == Label))
            {
                return;
            }

            if (NeedToRenderTexture)
            {
                using (var bmp = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    var Rectangle = new Rectangle(0, 0, bmp.Width, bmp.Height);
                    using (Graphics gr = Graphics.FromImage(bmp))
                    {
                        gr.Clear(System.Drawing.Color.Transparent);

                        gr.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
                        gr.DrawString(Label, Font, Brushes.White, Rectangle);

                        if (null != Tex)
                        {
                            Tex.Dispose();
                        }
                        Tex = new Texture(bmp);
                    }
                }
                NeedToRenderTexture = false;
            }

            GL.Enable(EnableCap.Blend);
            Tex.Bind();
            GL.Color4(Color);

            float w = Tex.Width / 2;
            float h = Tex.Height / 2;

            float Xc = 0.0f;
            float Yc = 0.0f;

            switch (TS)
            { 
                case TextSticking.TS_CENTER:
                    Xc = X;
                    Yc = Y;
                    break;
                case TextSticking.TS_TOP:
                    Xc = X;
                    Yc = Y - w;
                    break;
                case TextSticking.TS_BOTTOM:
                    Xc = X;
                    Yc = Y + w;
                    break;
                case TextSticking.TS_LEFT:
                    Xc = X - h;
                    Yc = Y;
                    break;
                case TextSticking.TS_RIGHT:
                    Xc = X + h;
                    Yc = Y;
                    break;
            }

            GL.Begin(BeginMode.Quads);

            GL.TexCoord2(0, 1);
            GL.Vertex2(Xc - w, Yc - h);

            GL.TexCoord2(1, 1);
            GL.Vertex2(Xc + w, Yc - h);

            GL.TexCoord2(1, 0);
            GL.Vertex2(Xc + w, Yc + h);

            GL.TexCoord2(0, 0);
            GL.Vertex2(Xc - w, Yc + h);

            GL.End();

            GL.Disable(EnableCap.Blend);
        }
    }

}
